﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AdvancedFeatures
{
    static class AdvancedFeatures
    {
        static void Main(string[] args)
        {
            Student[] students = 
            {
                new Student("Georgi", "Ivanov", 12),
                new Student("Stanislav", "Savov", 25),
                new Student("Petar", "Georgiev", 23),
                new Student("Stela", "Petrova", 18),
                new Student("Ivan", "Ivanov", 33),
                new Student("Asen", "Bogdanov", 24),
                new Student("Ivan", "Petrov", 33)
            };

            var nameOrderedStudents =
            from student in students
            where student.FirstName.CompareTo(student.LastName) < 0
            select student;

            Console.WriteLine("Student with first name before last");
            foreach (var student in nameOrderedStudents)
            {
                Console.WriteLine(student);
            }

            var rightAgeStudents =
            from student in students
            where (student.Age >= 18 & student.Age <= 24)
            select student;

            Console.WriteLine();
            Console.WriteLine("Student with age between 18 and 24");
            foreach (var student in rightAgeStudents)
            {
                Console.WriteLine(student + " " + student.Age);
            }

            var descendingOrderedStudents = 
            students.OrderByDescending(student => student.FirstName).ThenByDescending(student => student.LastName);

            Console.WriteLine();
            foreach (var item in descendingOrderedStudents)
            {
                Console.WriteLine(item);
            }

            int[] numbers = { 2, 12, 21, 42, 64, 32, 63 };
            var divisable = numbers.Where(number => (number % 21) == 0);
            Console.WriteLine();
            foreach (var item in divisable)
            {
                Console.WriteLine(item);
            }

            divisable =
            from number in numbers
            where (number % 21) == 0
            select number;
            Console.WriteLine();
            foreach (var item in divisable)
            {
                Console.WriteLine(item);
            }

            string text = "name";
            text = text.CapitalizeFirstLetter();
            Console.WriteLine(text);
        }

        private static StringBuilder SubString(this StringBuilder sBuilder, int index, int length)
        {
            if (index + length >= sBuilder.Length)
            {
                throw new IndexOutOfRangeException();
            }
            StringBuilder result = new StringBuilder();
            for (int i = index; i < length; i++)
            {
                result.Append(sBuilder[i]);
            }
            return result;
        }

        private static dynamic Sum<T>(this IEnumerable<T> collection)
        {
            dynamic sum = default(T);
            foreach (var item in collection)
            {
                sum = sum + item;
            }
            return sum;
        }

        private static dynamic Product<T>(this IEnumerable<T> collection)
        {
            dynamic product = default(T);
            foreach (var item in collection)
            {
                product = product * item;
            }
            return product;
        }

        private static dynamic Min<T>(this IEnumerable<T> collection)
        {
            dynamic min = default(T);
            foreach (var item in collection)
            {
                if (item < min)
                {
                    min = item;
                }
            }
            return min;
        }

        private static dynamic Max<T>(this IEnumerable<T> collection)
        {
            dynamic min = default(T);
            foreach (var item in collection)
            {
                if (item > min)
                {
                    min = item;
                }
            }
            return min;
        }

        private static dynamic Average<T>(this IEnumerable<T> collection)
        {
            dynamic average = default(T);
            int count = 0;
            foreach (var item in collection)
            {
                average = average + item;
                count++;
            }
            if (count != 0)
            {
                average = average / count;
            }
            return average;
        }

        private static string CapitalizeFirstLetter(this String text)
        {
            if (text.Length <= 0)
            {
                throw new NullReferenceException();
            }
            StringBuilder result = new StringBuilder(text);
            result[0] = Char.ToUpper(text[0]);
            text = result.ToString();
            return text;
        }
    }
}